package com.traffic.between.util;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;

import net.sf.json.JSONObject;

@SuppressWarnings("deprecation")
public class HttpClientUtils {
	private static Logger logger = Logger.getLogger(HttpClientUtils.class);

	private MultiThreadedHttpConnectionManager connectionManager = null;
	private int connectionTimeOut = 25000;
	private int socketTimeOut = 180000;
	private int maxConnectionPerHost = 20;
	private int maxTotalConnections = 20;
	private HttpClient client;

	public HttpClientUtils() {
		this.connectionManager = new MultiThreadedHttpConnectionManager();
		this.connectionManager.getParams().setConnectionTimeout(this.connectionTimeOut);
		this.connectionManager.getParams().setSoTimeout(this.socketTimeOut);
		this.connectionManager.getParams().setDefaultMaxConnectionsPerHost(this.maxConnectionPerHost);
		this.connectionManager.getParams().setMaxTotalConnections(this.maxTotalConnections);
		this.client = new HttpClient(this.connectionManager);
	}

	public String getUrl() {
		return "";
	}

	public String doPostJson(String strURL, Part[] parts) {
		HttpClient httpClient = this.client;
		PostMethod post = new PostMethod(strURL);
		String result = "";
		try {
			httpClient.getParams().setParameter("http.protocol.content-charset", "utf-8");
			post.setRequestEntity(new MultipartRequestEntity(parts, post.getParams()));
			httpClient.executeMethod(post);
			result = post.getResponseBodyAsString();
		} catch (HttpException e) {
			logger.error(e);
		} catch (IOException e) {
			logger.error(e);
		} finally {
			post.releaseConnection();
		}
		return result;
	}

	@SuppressWarnings("resource")
	public String doPostJson(String strURL, Object jsonParam) {
		logger.info("between- doPostJson()requestURL:" + strURL);
		DefaultHttpClient httpClient = new DefaultHttpClient();
		HttpPost post = new HttpPost(strURL);
		JSONObject resJson = null;
		String codeRes = null;
		try {
			httpClient.getParams().setParameter("http.protocol.content-charset", "utf-8");
			StringEntity entity = new StringEntity(jsonParam.toString(), "utf-8");
			entity.setContentEncoding("UTF-8");
			entity.setContentType("application/json");
			post.setEntity(entity);
			logger.info("between- doPostJson()params:" + JSONObject.fromObject(jsonParam) + ",dateformat:" + System.currentTimeMillis());
			HttpResponse result = httpClient.execute(post);

			String resData = EntityUtils.toString(result.getEntity());

			resJson = JSONObject.fromObject(resData);

			codeRes = new String(resJson.toString().getBytes("ISO-8859-1"), "UTF-8");

			logger.info("between- doPostJson()response{'code':" + resJson.get("resultCode").toString() + ",'desc':'"
					+ new String(resJson.get("resultMsg").toString().getBytes("ISO-8859-1"), "UTF-8") + "'}"
					+ ",dateformat:" + System.currentTimeMillis());
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return codeRes;
	}

	public static String doTestPostJson(String strURL, Object jsonParam) {
		logger.info("between- doTestPostJson()requestURL:" + strURL);
		@SuppressWarnings({ "resource" })
		DefaultHttpClient httpClient = new DefaultHttpClient();
		HttpPost post = new HttpPost(strURL);
		JSONObject resJson = null;
		String codeRes = null;
		try {
			httpClient.getParams().setParameter("http.protocol.content-charset", "utf-8");
			StringEntity entity = new StringEntity(jsonParam.toString(), "utf-8");
			entity.setContentEncoding("UTF-8");
			entity.setContentType("application/json");
			post.setEntity(entity);
			logger.info("请求参数:" + JSONObject.fromObject(jsonParam) + "____请求时间戳:" + System.currentTimeMillis());
			HttpResponse result = httpClient.execute(post);

			String resData = EntityUtils.toString(result.getEntity());

			resJson = JSONObject.fromObject(resData);

			codeRes = new String(resJson.toString().getBytes("ISO-8859-1"), "UTF-8");

			logger.info("请求返回结果集{'code':" + resJson.get("resultCode").toString() + ",'desc':'"
					+ new String(resJson.get("resultMsg").toString().getBytes("ISO-8859-1"), "UTF-8") + "'}"
					+ "____响应时间戳:" + System.currentTimeMillis());
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return codeRes;
	}

	public String doPost(String params, String enc) {
		logger.info("between- doPost()requestURL:" + params);
		String response = "";
		PostMethod postMethod = null;
		try {
			postMethod = new PostMethod(getUrl());
			postMethod.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=" + enc);
			postMethod.setRequestHeader("Connection", "close");
			postMethod.setRequestBody(params);

			long start = System.currentTimeMillis();
			int statusCode = this.client.executeMethod(postMethod);
			if (statusCode == 200) {
				response = postMethod.getResponseBodyAsString();
			} else {
				response = postMethod.getResponseBodyAsString();
				logger.info("between- doPost() = status: " + postMethod.getStatusCode() + "ERROR");
			}
			long end = System.currentTimeMillis();
			logger.info("耗时：" + ((end - start) / 1000L));
		} catch (HttpException e) {
			logger.error("发生致命的异常，可能是协议不对或者返回的内容有问题"+e.toString());
			e.printStackTrace();
		} catch (IOException e) {
			logger.error("发生网络异常"+e.toString());
			e.printStackTrace();
		} finally {
			if (postMethod != null) {
				postMethod.releaseConnection();
				postMethod = null;
			}
		}
		return response;
	}

	public String postJSONEntity(String api_url, Map<String, Object> params) throws Exception {
		logger.info("BACKURL-" + api_url);
		String body = JSON.toJSONString(params, new SerializerFeature[] { SerializerFeature.WriteNullNumberAsZero });
		StringEntity entity = new StringEntity(body, "utf-8");
		CloseableHttpClient httpclient = HttpClients.createDefault();

		HttpPost httppost = new HttpPost(api_url);
		httppost.addHeader("Content-Type", "application/json;charset=UTF-8");
		httppost.addHeader("Accept", "application/json");
		try {
			httppost.setEntity(entity);
			logger.info(EntityUtils.toString(entity));
			CloseableHttpResponse response = httpclient.execute(httppost);
			try {
				HttpEntity respEntity = response.getEntity();
				if (respEntity != null) {
					body = EntityUtils.toString(respEntity);
					logger.info(body);
				}
			} finally {
				response.close();
			}
		} finally {
			httpclient.close();
		}
		return body;
	}

	@SuppressWarnings("resource")
	public static String post(String url, String parameters) {
		String body = null;
		long startTime = 0L;
		long endTime = 0L;
		logger.info("parameters:" + parameters);
		DefaultHttpClient httpClient = new DefaultHttpClient();
		HttpPost method = new HttpPost(url);
		if (((((method != null) ? 1 : 0) & ((parameters != null) ? 1 : 0)) != 0) && (!("".equals(parameters.trim())))) {
			try {
				method.addHeader("Content-type", "application/json; charset=utf-8");
				method.setHeader("Accept", "application/json");
				method.setEntity(new StringEntity(parameters, Charset.forName("UTF-8")));
				startTime = System.currentTimeMillis();

				HttpResponse response = httpClient.execute(method);

				endTime = System.currentTimeMillis();
				int statusCode = response.getStatusLine().getStatusCode();

				logger.info("statusCode:" + statusCode);
				logger.info("调用API 花费时间(单位：毫秒)：" + (endTime - startTime));
				if (statusCode != 200) {
					logger.error("Method failed:" + response.getStatusLine());
				}

				body = EntityUtils.toString(response.getEntity());
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		return body;
	}

	public String doPost(Map<String, String> params, String enc) {
		logger.info("requestClient params:" + JSONObject.fromObject(params));
		String response = "";
		PostMethod postMethod = null;
		try {
			postMethod = new PostMethod(getUrl());

			postMethod.setRequestHeader("Content-Type", "application/soap+xml;");
			postMethod.setRequestHeader("Connection", "close");

			Set<String> keySet = params.keySet();
			for (String key : keySet) {
				String value = (String) params.get(key);
				postMethod.addParameter(key, value);
			}
			long start = System.currentTimeMillis();

			int statusCode = this.client.executeMethod(postMethod);
			if (statusCode == 200) {
				response = postMethod.getResponseBodyAsString();
			} else {
				response = postMethod.getResponseBodyAsString();
				logger.info("响应状态码 = " + postMethod.getStatusCode() + "ERROR");
			}
			long end = System.currentTimeMillis();
			logger.info("耗时：" + ((end - start) / 1000L));
		} catch (HttpException e) {
			logger.error("发生致命的异常，可能是协议不对或者返回的内容有问题");
			e.printStackTrace();
		} catch (IOException e) {
			logger.error("发生网络异常");
			e.printStackTrace();
		} finally {
			if (postMethod != null) {
				postMethod.releaseConnection();
				postMethod = null;
			}
		}

		return response;
	}

	public String doPost(Map<String, String> params, String enc, String url) {
		logger.info("requestClient params:" + JSONObject.fromObject(params));
		String response = "";
		PostMethod postMethod = null;
		try {
			postMethod = new PostMethod(url);

			postMethod.setRequestHeader("Content-Type", "application/soap+xml;");
			postMethod.setRequestHeader("Connection", "close");

			Set<String> keySet = params.keySet();
			for (String key : keySet) {
				String value = (String) params.get(key);
				postMethod.addParameter(key, value);
			}
			long start = System.currentTimeMillis();

			int statusCode = this.client.executeMethod(postMethod);
			if (statusCode == 200) {
				response = postMethod.getResponseBodyAsString();
			} else {
				response = postMethod.getResponseBodyAsString();
				logger.info("响应状态码 = " + postMethod.getStatusCode() + "ERROR");
			}
			long end = System.currentTimeMillis();
			logger.info("耗时：" + ((end - start) / 1000L));
		} catch (HttpException e) {
			logger.error("发生致命的异常，可能是协议不对或者返回的内容有问题[" + params + "]: \n" + e.getMessage());
			e.printStackTrace();
		} catch (IOException e) {
			logger.error("发生网络异常[" + params + "]: \n" + e.getMessage());
			e.printStackTrace();
		} finally {
			if (postMethod != null) {
				postMethod.releaseConnection();
				postMethod = null;
			}
		}

		return response;
	}

	public String doGet(Map<String, Object> params, String enc, String path) {
		String response = "";
		GetMethod getMethod = null;
		StringBuffer strtTotalURL = new StringBuffer("");

		strtTotalURL.append(path).append("?").append(parseUrlO(params, enc));
		try {
			getMethod = new GetMethod(strtTotalURL.toString());
			getMethod.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=" + enc);

			getMethod.setRequestHeader("Connection", "close");

			int statusCode = this.client.executeMethod(getMethod);
			if (statusCode == 200)
				response = getMethod.getResponseBodyAsString();
			else
				logger.info("响应状态码 = " + getMethod.getStatusCode());
		} catch (HttpException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (getMethod != null) {
				getMethod.releaseConnection();
				getMethod = null;
			}
		}

		return response;
	}

	public String doGet(Map<String, String> params, String enc) {
		String response = "";
		GetMethod getMethod = null;
		StringBuffer strtTotalURL = new StringBuffer("");

		if (strtTotalURL.indexOf("?") == -1)
			strtTotalURL.append(getUrl()).append("?").append(parseUrl(params, enc));
		else {
			strtTotalURL.append(getUrl()).append("&").append(parseUrl(params, enc));
		}
		try {
			getMethod = new GetMethod(strtTotalURL.toString());
			getMethod.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=" + enc);

			getMethod.setRequestHeader("Connection", "close");

			int statusCode = this.client.executeMethod(getMethod);
			if (statusCode == 200) {
				response = getMethod.getResponseBodyAsString();
			}

		} catch (HttpException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (getMethod != null) {
				getMethod.releaseConnection();
				getMethod = null;
			}
		}

		return response;
	}

	public String doGet(String url) {
		String response = "";
		GetMethod getMethod = null;
		try {
			getMethod = new GetMethod(url);
			getMethod.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;");

			getMethod.setRequestHeader("Connection", "close");

			int statusCode = this.client.executeMethod(getMethod);
			if (statusCode == 200) {
				response = getMethod.getResponseBodyAsString();
			}

		} catch (HttpException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (getMethod != null) {
				getMethod.releaseConnection();
				getMethod = null;
			}
		}

		return response;
	}

	private String parseUrlO(Map<String, Object> map, String valueEnc) {
		if ((null == map) || (map.keySet().size() == 0)) {
			return "";
		}
		StringBuffer url = new StringBuffer();
		Set<String> keys = map.keySet();
		for (Iterator<String> it = keys.iterator(); it.hasNext();) {
			String key = (String) it.next();
			if (map.containsKey(key)) {
				String val = (String) map.get(key);
				String str = (val != null) ? val : "";
				try {
					str = URLEncoder.encode(str, valueEnc);
				} catch (UnsupportedEncodingException e) {
					e.printStackTrace();
				}
				url.append(key).append("=").append(str).append("&");
			}
		}
		String strURL = "";
		strURL = url.toString();
		if ("&".equals("" + strURL.charAt(strURL.length() - 1))) {
			strURL = strURL.substring(0, strURL.length() - 1);
		}

		return strURL;
	}

	private String parseUrl(Map<String, String> map, String valueEnc) {
		if ((null == map) || (map.keySet().size() == 0)) {
			return "";
		}
		StringBuffer url = new StringBuffer();
		Set<String> keys = map.keySet();
		for (Iterator<String> it = keys.iterator(); it.hasNext();) {
			String key = (String) it.next();
			if (map.containsKey(key)) {
				String val = (String) map.get(key);
				String str = (val != null) ? val : "";
				try {
					str = URLEncoder.encode(str, valueEnc);
				} catch (UnsupportedEncodingException e) {
					e.printStackTrace();
				}
				url.append(key).append("=").append(str).append("&");
			}
		}
		String strURL = "";
		strURL = url.toString();
		if ("&".equals("" + strURL.charAt(strURL.length() - 1))) {
			strURL = strURL.substring(0, strURL.length() - 1);
		}

		return strURL;
	}

	public void setConnectionTimeOut(int connectionTimeOut) {
		this.connectionTimeOut = connectionTimeOut;
	}

	public void setSocketTimeOut(int socketTimeOut) {
		this.socketTimeOut = socketTimeOut;
	}

	public void setMaxConnectionPerHost(int maxConnectionPerHost) {
		this.maxConnectionPerHost = maxConnectionPerHost;
	}

	public void setMaxTotalConnections(int maxTotalConnections) {
		this.maxTotalConnections = maxTotalConnections;
	}
}